package org.example.sms02;

import org.example.StudentManagementSystem.JuniorStudent;
import org.example.StudentManagementSystem.Student;
import org.example.StudentManagementSystem.primaryStudent;
import org.example.constant.EnrollmentStatus;

import java.io.*;
import java.time.LocalDate;
import java.time.format.DateTimeParseException;
import java.util.*;

public class StudentManagementSystem02 {
    private ArrayList<Student> students = new ArrayList<>();

    // 1.添加学生信息的通用方法
    public void addStudent(Student student) {
        try {
            if (student != null && validateStudentEmail(student)) {
                students.add(student);
            }
        } catch (Exception e) {
            System.out.println("添加学生时出错：" + e.getMessage());
            e.printStackTrace();
        }
//        else {
//            System.out.println("学号：" + student.getStudentId() + "，姓名："
//                    + student.getStudentName() + "，邮箱⭐："
//                    + student.getMail() + "，不符合邮箱格式，添加失败");
//       }
    }

    //校验邮箱方法
    public boolean validateStudentEmail(Student student) {
        if (student == null || student.getMail() == null) {
            throw new RuntimeException("学生为null或者邮箱为null");
        } else {
            return student.getMail().matches("\\w+@\\w+\\.\\w+");
        }

    }

    //2.展示学生信息：
    public void showAllStudents(Collection<Student> students) {
        try {
            int i = 1;
            for (Student student : students) {
                System.out.println((i++) + " " + student);
            }
        } catch (Exception e) {
            System.out.println("显示学生信息是出错" + e.getMessage());
            e.printStackTrace();
        }
    }

    //更新学生
    public Student updateStudentByIndex(int number, Student newstudent) {
        try {
            if (number >= 1 && number <= students.size()) {
                return students.set(number - 1, newstudent);
            } else {
                //            System.out.println("不存在序号为" + number + "的学生信息");
                //            return null;
                throw new RuntimeException("指定的学生序号超出范围：" + number);
            }
        } catch (RuntimeException e) {
            System.out.println("更新学生信息时出错：" + e.getMessage());
            e.printStackTrace();
            return null;
        }
    }

    public void showAllStudents() {
        showAllStudents(students);
    }

    //3.判断学生是否存在
    public boolean containsStudent(Student student) {
        try {
            return students.contains(student);
        } catch (Exception e) {
            throw new RuntimeException(e);//将异常对象进一步封装，将来可以打印出e的信息
        }
    }

    //4.根据学生学号查找某个学生
    public Student selectByStudentId(int studentID) {
        try {
            for (Student student : students) {
                if (student.getStudentId() == studentID) {
                    return student;
                }
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return null;//说明该学号的学生不存在
    }

    //5.求学生平均成绩
    public int getAvgrageScoreBySubject(String subject) {
        try {
            int totalScore = 0;
            int count = 0;
            for (Student student : students) {
                int score = getScoreBySubject(student, subject);
                if (score != 0) {
                    totalScore += score;
                    count++;
                }
            }
            return students.size() == 0 ? 0 : totalScore / count;
        } catch (Exception e) {
            throw new RuntimeException("计算平均分时出错", e);
        }
    }

    public int getScoreBySubject(Student student, String subject) {
        try {
            switch (subject) {
                case "语文" -> {
                    return student.getChinese();
                }
                case "数学" -> {
                    return student.getMath();
                }
                case "物理" -> {
                    if (student instanceof JuniorStudent juniorStudent) {
                        return juniorStudent.getPhysics();
                    }
                    return 0;
                }
                case "历史" -> {
                    if (student instanceof JuniorStudent juniorStudent) {
                        return juniorStudent.getHistory();
                    }
                    return 0;
                }
                default -> {
                    return 0;
                }
            }
        } catch (Exception e) {
            throw new RuntimeException("获取当前学生" + student + "对应科目" + subject + "时出错", e);
        }
    }

    //6.判断指定日期之前的学生
    public Collection getStudentsEnrolledBefore(String date) {
        Collection temp = new ArrayList();
        try {
            //创建一个容器专门用来储存符合条件的学生
            for (Student student : students) {
                if (student.getEnrollmentDate() != null) {
                    if (student.getEnrollmentDate().isBefore(LocalDate.parse(date))
                            || student.getEnrollmentDate().isEqual(LocalDate.parse(date))) {
                        temp.add(student);
                    }
                }
            }
        } catch (DateTimeParseException e) {
            System.out.println("解析日期" + date + "时出错" + e.getMessage());
            e.printStackTrace();
        } catch (Exception e) {
            throw new RuntimeException("判断指定日期之前入学的学生出错", e);
        }
        return temp;
    }

    //判断指定日期之后的学生
    public Collection getStudentsEnrolledAfter(String date) {
        //创建一个容器专门用来储存符合条件的学生
        Collection temp = new ArrayList();
        try {
            for (Student student : students) {
                if (student.getEnrollmentDate() != null) {
                    if (student.getEnrollmentDate().isAfter(LocalDate.parse(date))
                            || student.getEnrollmentDate().isEqual(LocalDate.parse(date))) {
                        temp.add(student);
                    }
                }
            }
        } catch (DateTimeParseException e) {
            System.out.println("解析日期" + date + "时出错" + e.getMessage());
            e.printStackTrace();
        } catch (Exception e) {
            throw new RuntimeException("判断指定日期之后入学的学生出错", e);
        }
        return temp;
    }

    //7.随机点名方法
    public Student randomRollCall() {
//        Random random = new Random();
//        int randonIndex = random.nextInt(students.size());
//        return students.get(randonIndex);
        try {
            return students.get(new Random().nextInt(students.size()));
        } catch (Exception e) {
            System.out.println("随机点名出错" + e.getMessage());
            e.printStackTrace();
            return null;
        }
    }

    //8.按照总成绩进行排序
    public void sortByTotalScore() {
        //1.构建一个TreeSet，并且利用比较器指定比较规则
//        TreeSet<Student> temps = new TreeSet<>(new Comparator<Student>() {
//            @Override
//            public int compare(Student o1, Student o2) {
//                //如果两个学生总分相同，姓名不同就会存不进去↓↓👇
//                //return o2.getTotalScore() - o1.getTotalScore();
//                int result = o2.getTotalScore() - o1.getTotalScore();
//                int nameResule = o2.getStudentName().compareTo(o1.getStudentName());
//                if (result == 0) {
//                    if (nameResule == 0) {
//                        return o2.getStudentId() - o1.getStudentId();
//                    } else {
//                        //总分相同，姓名不同
//                        return o2.getStudentName().compareTo(o1.getStudentName());
//                    }
//                } else {
//                    return result;//总分不同
//                }
//            }
//        });
//        temps.addAll(students);//将指定的集合中的元素拷贝到当前集合
//        students.clear();
//        students.addAll(temps);
        try {
            students.sort(new Comparator<Student>() {
                @Override
                public int compare(Student o1, Student o2) {
                    return o2.getTotalScore() - o1.getTotalScore();
                }
            });
        } catch (Exception e) {
            System.out.println("排序过程中出错" + e.getMessage());
            e.printStackTrace();
        }
    }

    //9.获取指定科目成绩最高（最低）的学生
    public Student findStudentWithHighestScore(String subject) {
        try {
            return Collections.max(students, new Comparator<Student>() {
                @Override
                public int compare(Student s1, Student s2) {
                    return getScoreBySubject(s1, subject) - getScoreBySubject(s2, subject);
                }
            });
        } catch (NoSuchElementException e) {
            System.out.println("没有找到如何学生" + e.getMessage());
            e.printStackTrace();
            return null;
        } catch (ClassCastException e) {
            System.out.println("学生的分数不可比较" + e.getMessage());
            e.printStackTrace();
            return null;
        }
    }

    public Student findStudentLowestScore(String subject) {
        try {
            return Collections.min(students, new Comparator<Student>() {
                @Override
                public int compare(Student o1, Student o2) {
                    return getScoreBySubject(o1, subject) - getScoreBySubject(o2, subject);
                }
            });
        } catch (NoSuchElementException e) {
            System.out.println("没有找到如何学生" + e.getMessage());
            e.printStackTrace();
            return null;
        } catch (ClassCastException e) {
            System.out.println("学生的分数不可比较" + e.getMessage());
            e.printStackTrace();
            return null;
        }
    }

    //10.根据科目统计相同成绩的学生人数
    public Map<Integer, Integer> getScoreStatisticsBySubject(String subject) {
        Map<Integer, Integer> scoreStatistics = new HashMap<>();
        try {
            for (Student student : students) {
                Integer score = getScoreBySubject(student, subject);
                if (scoreStatistics.containsKey(score)) {
                    scoreStatistics.put(score, scoreStatistics.get(score) + 1);
                } else {
                    scoreStatistics.put(score, 1);
                }
            }
        } catch (NullPointerException e) {
            System.out.println("处理学生成绩出错" + e.getMessage());
            e.printStackTrace();
        }
        return scoreStatistics;
    }

    //11.模拟学生头像的上传
    public void uploadStudentAvatar(Student student, String localFilePath, String serverPath) throws IOException {
        //1.利用FileInputStream关联读的文件，然后再利用BufferedInputStream包装FileInputStream，目的提高读效率
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(localFilePath));
        //2.将上传的图片进行名称的唯一性处理***
        //D:/img/abc.jpg
        String fileName = new File(localFilePath).getName();//获取文件的名称
        String extension = fileName.substring(fileName.lastIndexOf("."));//截取文件的后缀名 .jpg
        String newFileName = UUID.randomUUID().toString() + extension; //例如： adsadas-1213123-dfgdfg.jpg

        //3.利用FileOutputStream关联写的文件，然后再利用BufferedOutputStream包装FileOutputStream，目的提高读效率
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(serverPath + "/" + newFileName));

        //4.读写操作
        int b;
        while ((b = bis.read()) != 1) {
            bos.write(b);
        }
        //5.关流释放资源
        bis.close();
        bos.close();
        //6.将该上传的图片绑定到当前学生
        student.setAvatar(serverPath + "/" + newFileName);
    }

    //12.从硬盘上加载学生数据
    public void loadStudentsFromFile(String filePath) throws IOException {
        //先利用FileReader去关联指定的文件路径
        //再利用BufferedReader进行包装，为了使用ReadLine()方法
//        File file = new File(filePath);
//        BufferedReader br = new BufferedReader(new FileReader(file));
        InputStream is = StudentManagementSystem02.class.getClassLoader().getResourceAsStream("中学生信息02.txt");
        BufferedReader br = new BufferedReader(new InputStreamReader(is));

        //逐行读取指定的文件
        String line;
        while ((line = br.readLine()) != null) {
            //例如：小学生：20241316,小新,77,81,2013-10-12,233434@qq.com
            //小学生和中学生通用属性的数据封装
            String[] data = line.split(",");
            Integer studentId = Integer.parseInt(data[0]);
            String studentName = data[1];
            Integer chinese = Integer.parseInt(data[2]);
            Integer math = Integer.parseInt(data[3]);
            LocalDate enrollmentDate = LocalDate.parse(data[4]);
            String mail = data[5];
            EnrollmentStatus enrollmentStatus = EnrollmentStatus.getEnumByDesc(data[6]);//根据中文学籍名称获取对应的枚举常量
            if (filePath.equals("中学生信息02.txt")) {
                //封装中学生发特有信息：历史和物理成绩
                //例如：中学生：20241316,大新,97,81,2013-10-12,233434123@qq.com,100,98
                Integer history = Integer.parseInt(data[7]);
                Integer physics = Integer.parseInt(data[8]);
                JuniorStudent juniorStudent = new JuniorStudent(studentId,
                        studentName, chinese, math, enrollmentDate, mail, enrollmentStatus, history, physics);
                students.add(juniorStudent);
            } else if (filePath.equals("小学生信息02.txt")) {
                primaryStudent primaryStudent = new primaryStudent(studentId,
                        studentName, chinese, math, enrollmentDate, mail, enrollmentStatus);
                students.add(primaryStudent);
            }
        }
        br.close();

    }

    //13.写入排名后的学生信息到硬盘
    public void writeRankedStudentToFile(String resultPath) throws IOException {
        //从低到高进行排名
        sortByTotalScore();
        //将排好序的学生信息写入指定文件
        BufferedWriter bw = new BufferedWriter(new FileWriter(resultPath));
        for (Student student : students) {
            bw.write(student.toString());
            bw.newLine();//每写一个学生信息就换行
        }
        bw.close();
    }


}
